package sliding_window

/*
给出非负整数数组 A ，返回两个非重叠（连续）子数组中元素的【最大和】，子数组的长度分别为 L 和 M。（这里需要澄清的是，长为 L 的子数组可以出现在长为 M 的子数组之前或之后。）
从形式上看，返回最大的 V，而 V = (A[i] + A[i+1] + ... + A[i+L-1]) + (A[j] + A[j+1] + ... + A[j+M-1]) 并满足下列条件之一：

0 <= i < i + L - 1 < j < j + M - 1 < A.length, 或
0 <= j < j + M - 1 < i < i + L - 1 < A.length.

示例 1：
输入：A = [0,6,5,2,2,5,1,9,4], L = 1, M = 2
输出：20
解释：子数组的一种选择中，[9] 长度为 1，[6,5] 长度为 2。

示例 2：
输入：A = [3,8,1,3,2,1,8,9,0], L = 3, M = 2
输出：29
解释：子数组的一种选择中，[3,8,1] 长度为 3，[8,9] 长度为 2。

示例 3：
输入：A = [2,1,5,6,0,9,5,0,3,8], L = 4, M = 3
输出：31
解释：子数组的一种选择中，[5,6,0,9] 长度为 4，[0,3,8] 长度为 3。

*/

/*
题解：
1.考虑题意: 必然存在一条分界线把 A 拆分成两半，存在两大类情况：
2.长度为 L 的连续子数组在左边, 长度为 M 的连续子数组在右边
3.或者长度为 M 的连续子数组在左边, 长度为 L 的连续子数组在右边

引入
1.dp[i][0]: 从 A[0]-A[i] 连续 L 长度子数组最大的元素和
2.dp[i][1]: 从 A[0]-A[i] 连续 M 长度子数组最大的元素和
3.dp[i][2]: 从 A[i]-A[A.size()-1] 连续 L 长度子数组最大的元素和
4.dp[i][3]: 从 A[i]-A[A.size()-1] 连续 M 长度子数组最大的元素和
5.某些超出范围的下标, 值设置为 0 (默认值)
首先用滑动窗口计算了 dp, 然后将 dp 分成两组, 计算两大类情况下的结果，取最大值返回即可。
*/
func maxSumTwoNoOverlap(nums []int, firstLen int, secondLen int) int {

	res, n := 0, len(nums)
	for i := 1; i < n; i++ {
		nums[i] += nums[i-1] //前缀和
	}

	i := firstLen + secondLen - 1 //最后一位下标值
	res = nums[i]
	firstSum := nums[firstLen-1]
	secondSum := nums[secondLen-1]
	for i = firstLen + secondLen; i < n; i++ {
		//后面留一段给secondLen，前面firstLen的最大和
		firstSum = max(firstSum, nums[i-secondLen]-nums[i-firstLen-secondLen])
		//后面留一段给firstLen，前面secondLen的最大和
		secondSum = max(secondSum, nums[i-firstLen]-nums[i-firstLen-secondLen])
		res = max(res,
			max(firstSum+nums[i]-nums[i-secondLen], //前面是 firstLen + 当前secondLen
				secondSum+nums[i]-nums[i-firstLen])) //前面是 secondLen + 当前的firstLen
	}
	return res
}

/*
//golang 版本
func maxSumTwoNoOverlap(nums []int, firstLen int, secondLen int) int {
	res, n := 0, len(nums)
	for i := 1; i < n; i++ {
		nums[i] += nums[i-1]
	}

	i := firstLen + secondLen - 1
	res = nums[i]
	firstSum := nums[firstLen-1]
	secondSum := nums[secondLen-1]
	for i = firstLen + secondLen; i < n; i++ {
		firstSum = maxSumTwoNoOverlapMax(firstSum, nums[i-secondLen]-nums[i-firstLen-secondLen])
		secondSum = maxSumTwoNoOverlapMax(secondSum, nums[i-firstLen]-nums[i-firstLen-secondLen])
		res = maxSumTwoNoOverlapMax(res, maxSumTwoNoOverlapMax(firstSum+nums[i]-nums[i-secondLen], secondSum+nums[i]-nums[i-firstLen]))
	}
	return res
}

*/
